写在最前面
- 适用于 react 初学者,需要了解怎么优雅的处理获取数据操作。
- loading 和 error 逻辑怎么处理?
- 使用 Promises 和 Async/Await, 高阶组件获取数据?
怎么优雅的使用 react 获取数据
- 普通刚开始学习 react 的初学者都会有一个问题,我们需要展示一列数据。但是我们需要在 react 的生命周期(lifecycle)中哪里去获取这个数据合适啦?
- 现在我们知道
componentDidMount
在生命周期中
使用 JavaScript Promises 去处理数据
- 在
componentDidMount()
使用promise
import React, { Component } from 'react';class App extends Component { constructor(props) { super(props); this.state = { data: null, }; } componentDidMount() { fetch('https://api.mydomain.com') .then(response => response.json()) .then(data => this.setState({ data })); } ...}export default App;复制代码
当然我们可以使用第三方 api,当我们获取数据成功以后。然后就被存储到了 react 的
this.setState()
方法中。然后render()
会重新渲染,然后我们就可以看到我们的数据展示了。
...class App extends Component { ... render() { const { hits } = this.state; return (
- {hits.map(hit =>
- {hit.title} )}
note: 如果你想了解最新的 react hooks 来获取处理数据的方法:
怎么优雅的处理 loading 和 error?
- 一般在获取数据的时候我们需要处理几种情况,加载中 loading,出错 error,加载成功。所以一般情况下我们会把 loading 和 error 状态存在 state 中。
loading 加载中处理
...class App extends Component { constructor(props) { super(props); this.state = { hits: [], isLoading: false, }; } componentDidMount() { this.setState({ isLoading: true }); fetch(API + DEFAULT_QUERY) .then(response => response.json()) .then(data => this.setState({ hits: data.hits, isLoading: false })); } ...}export default App;复制代码
- 使用一个 Loading 的提示
...class App extends Component { ... render() { const { hits, isLoading } = this.state; if (isLoading) { returnLoading ...
; } return (
- {hits.map(hit =>
- {hit.title} )}
Error 处理
- 初始化 error
...class App extends Component { constructor(props) { super(props); this.state = { hits: [], isLoading: false, error: null, }; } ...}复制代码
- 当我们使用
promise
的使用,使用catch()
去捕捉错误。
...class App extends Component { ... componentDidMount() { this.setState({ isLoading: true }); fetch(API + DEFAULT_QUERY) .then(response => response.json()) .then(data => this.setState({ hits: data.hits, isLoading: false })) .catch(error => this.setState({ error, isLoading: false })); } ...}复制代码
- react 原生的API 不能处理一些错误的状态码,这里需要手动处理一下。
...class App extends Component { ... componentDidMount() { this.setState({ isLoading: true }); fetch(API + DEFAULT_QUERY) .then(response => { if (response.ok) { return response.json(); } else { throw new Error('Something went wrong ...'); } }) .then(data => this.setState({ hits: data.hits, isLoading: false })) .catch(error => this.setState({ error, isLoading: false })); } ...}复制代码
- 当然,我们完全可以展示错误提示。
...class App extends Component { ... render() { const { hits, isLoading, error } = this.state; if (error) { return{error.message}
; } if (isLoading) { returnLoading ...
; } return (
- {hits.map(hit =>
- {hit.title} )}
使用 Axios 来获取数据
import React, { Component } from 'react';import axios from 'axios';const API = 'https://hn.algolia.com/api/v1/search?query=';const DEFAULT_QUERY = 'redux';class App extends Component { constructor(props) { super(props); this.state = { hits: [], isLoading: false, error: null, }; } componentDidMount() { this.setState({ isLoading: true }); axios.get(API + DEFAULT_QUERY) .then(result => this.setState({ hits: result.data.hits, isLoading: false })) .catch(error => this.setState({ error, isLoading: false })); } ...}export default App;复制代码
使用 Async/Await 来获取数据
import React, { Component } from 'react';import axios from 'axios';const API = 'https://hn.algolia.com/api/v1/search?query=';const DEFAULT_QUERY = 'redux';class App extends Component { ... async componentDidMount() { this.setState({ isLoading: true }); try { const result = await axios.get(API + DEFAULT_QUERY); this.setState({ hits: result.data.hits, isLoading: false }); } catch (error) { this.setState({ error, isLoading: false }); } } ...}export default App;复制代码
使用 高阶组件来获取数据
- 不明白高阶组件的同学可以看看我以前的文章:
const withFetching = (url) => (Component) => class WithFetching extends React.Component { constructor(props) { super(props); this.state = { data: null, isLoading: false, error: null, }; } componentDidMount() { this.setState({ isLoading: true }); axios.get(url) .then(result => this.setState({ data: result.data, isLoading: false })) .catch(error => this.setState({ error, isLoading: false })); } render() { return; } }复制代码
- 怎么使用
const withFetching = (url, query) => (Comp) => ...复制代码